home *** CD-ROM | disk | FTP | other *** search
- include qlib.inc ;setup
- include dos.inc
- include string.inc
- include conio.inc
- include stdlib.inc
-
- .data?
- align 4
- _bak dd ?
- _width dd ?
- _pad dd ? ;used with %s when width is used
- _dec dd ? ;width after . (%f)
-
- tempstr db 64 dup(?)
-
- _pos db ? ;flag : use positive sign on signed #'s
- _zero db ? ;flag : do not remove leading zeros
- _dot db ? ;flag : . used with %f
- _decu db ? ;flag : is _dec used?
- _typ db ? ;type : the char after the % (ie: d,x,X,c,s,f,etc.)
-
- epos dd ? ;used for %f and %e
- esiz dd ?
-
- .code
- decode_per proc private uses ecx
- ; in : esi=string (right after %)
- ; : ebx=varargs
- ; out : eax=# bytes needed
- ; : _typ=char (c,s,d...)
- ; : _width=byte (max=9999)
- ; : _zero = T/F
- ; : _pos = T/F
-
- local m:byte
-
- mov m,0
- mov _pos,0
- mov _zero,0
- mov _width,0
- mov _dot,0
- mov _dec,0 ;decimal width for decimals (BC uses 6 which is dumb)
- mov _decu,0
- mov _bak,esi
- @@:
- lodsb
- gotit:
- .if al=='.'
- .if _dot
- jmp bad
- .endif
- inc _dot
- mov m,0
- jmp @b
- .endif
- .if (al=='0') && (!_zero) && (!_width) && (!_dot)
- inc _zero
- jmp @b
- .endif
- .if (al=='+')
- .if _pos
- jmp bad
- .endif
- inc _pos
- jmp @b
- .endif
- .if (al>='0') && (al<='9')
- .if _dot
- mov _decu,1
- .if m > 5
- jmp @b ;ignore # (it's large enough)
- .endif
- mov ecx,_dec
- imul ecx,10
- inc m
- sub al,'0'
- xor ah,ah
- add cx,ax
- mov _dec,ecx
- jmp @b
- .endif
- .if m > 5
- jmp @b ;ignore # (it's large enough)
- .endif
- mov ecx,_width
- imul ecx,10
- inc m
- sub al,'0'
- xor ah,ah
- add cx,ax
- mov _width,ecx
- jmp @b
- .endif
-
- .if al=='f'
- mov _typ,al
- mov eax,64
- add ebx,4 ;add an aditional 4bytes cause floats are 64bit (double!)
- jmp done
- .endif
- .if al=='e'
- mov _typ,al
- mov eax,64
- add ebx,4 ;add an aditional 4bytes cause floats are 64bit (double!)
- jmp done
- .endif
- .if (_dot)
- jmp bad
- .endif
-
- .if al=='b'
- mov _typ,al ;binary
- mov eax,33
- jmp done
- .endif
- .if al=='o'
- mov _typ,al ;octal
- mov eax,17
- jmp done
- .endif
- .if al=='x'
- mov _typ,al ;hex
- mov eax,9
- jmp done
- .endif
- .if al=='X'
- mov _typ,al ;HEX
- mov eax,9
- jmp done
- .endif
- .if al=='u'
- mov _typ,al ;unsigned
- mov eax,11
- jmp done
- .endif
- .if al=='d' || al=='i' ;signed
- mov _typ,al
- mov eax,12
- jmp done
- .endif
-
- .if (_zero) || (_pos) || (_dot)
- jmp bad
- .endif
-
- .if al=='s' ;string
- mov _typ,al
- mov eax,[ebx]
- callp strlen,eax
- .if eax < _width
- mov ecx,_width
- mov _pad,ecx
- sub _pad,eax
- mov eax,ecx
- .endif
- jmp done
- .elseif al=='c'
- mov _typ,al
- mov eax,1
- jmp done
- .endif
- jmp bad
-
- done:
- .if _width > eax ;make sure to return largest #
- mov eax,_width
- .endif
- add ebx,4
- ret
- bad:
- mov esi,_bak
- mov _typ,0
- xor eax,eax
- ret
- decode_per endp
-
- _printf_siz proc,str1:dword,args:vararg
- ;calculate maximum RAM required for string when all % expanded.
- ; out : eax = max size needed
- lea eax,args
- callp _vprintf_siz,str1,eax
- ret
- _printf_siz endp
-
- _vprintf_siz proc,str1:dword,args:dword
- local siz:dword
- pushad
- mov esi,str1
- mov ebx,args
- mov siz,0
- @@:
- cmp byte ptr[esi],0
- jz @f
- cmp byte ptr[esi],'%'
- jz @@per
- inc siz
- inc esi
- jmp @b
- @@per:
- inc esi
- cmp byte ptr[esi],'%'
- jnz @@per2
- inc esi
- inc siz ;just one % will go out
- jmp @b
- @@per2:
- call decode_per
- .if !eax
- inc siz ;for the % (w/ error)
- .elseif
- add siz,eax
- .endif
- jmp @b
- @@:
- inc siz ;for the 0
- popad
- mov eax,siz
- ret
- _vprintf_siz endp
-
- ;prints into string
- sprintf proc,buf:dword,str1:dword,args:vararg
- lea eax,args
- callp vsprintf,buf,str1,eax
- ret
- sprintf endp
-
- vsprintf proc,buf:dword,str1:dword,args:dword
- ;prints C type string from src => dest
-
- ; % [+][0][width][S] type
- ; type=[d],[o],[x],[X],[b],[c],[s],[%],[f]
-
- ; +=use + when printing signed #'s
- ; 0=keep all leading zeros
- ; S=signed modifier (error if used with 'c' or 's')
- ; x,X=hex output (as in C)
- ; b=binary output
- ; d=decimal output
- ; c=char
- ; s=string
- ; f=double (DO NOT USE FLOAT)
-
- ; NO LOCALS ALLOWED
-
- ; FIX : v2.00 Beta #2 : this was not preserving regs!
-
- pushad
-
- mov esi,str1
- mov edi,buf
- mov ebx,args
-
- mov ebp,ebx
- @@top:
- mov al,[esi]
- cmp al,0
- jz __end
- cmp al,'%'
- jz @@per
- @@per1:
- movsb
- jmp @@top
- @@per: ; % is use
- inc esi
- mov al,[esi]
- cmp al,'%'
- jz @@per1 ;2 % = 1 %
- mov ebx,ebp
- call decode_per
- mov al,_typ
- cmp al,0
- jz __end
-
- cmp al,'u'
- jz @@peru
- cmp al,'i'
- jz @@perd
- cmp al,'d'
- jz @@perd
- cmp al,'x'
- jz @@perx
- cmp al,'X'
- jz @@perxc
- cmp al,'c'
- jz @@perc
- cmp al,'o'
- jz @@pero
- cmp al,'b'
- jz @@perb
- cmp al,'e'
- jz @@perf
- cmp al,'f'
- jz @@perf
- ;must be 's'
- .if _width && _pad
- mov al,32
- mov ecx,_pad
- rep stosb
- .endif
- callp strcpy,edi,[ebp]
- callp strlen,[ebp]
- add edi,eax
- add ebp,4
- jmp @@top
- @@perf:
- .if _dec > 40
- mov _dec,40 ;no more than this is needed
- .endif
- .if !_decu
- mov _dec,6
- .endif
- .if al=='f'
- callp ftoa,REAL8 PTR[ebp],offset tempstr,_dec
- .else ;'e'
- callp etoa,REAL8 PTR[ebp],offset tempstr,_dec
- .endif
- jmp addfstr
- @@perb:
- callp num2str,[ebp],offset tempstr,2
- jmp addstr
- @@pero:
- callp num2str,[ebp],offset tempstr,8
- jmp addstr
- @@perd:
- callp num2strs,[ebp],offset tempstr,10 ;signed!
- jmp addstr
- @@peru:
- callp num2str,[ebp],offset tempstr,10 ;unsigned!
- jmp addstr
- @@perx: ;hex w/ lower case
- callp num2str,[ebp],offset tempstr,16
- jmp addstr
- @@perxc: ;hex w/capitals
- callp num2strc,[ebp],offset tempstr,16
- jmp addstr
- @@perc:
- mov al,[ebp]
- mov [edi],al
- inc edi
- add ebp,4 ;no byte pushes possible
- jmp @@top
- __end:
- mov byte ptr[edi],0
- popad
- xor eax,eax
- ret
- addstr:
- add ebp,4 ;move to next var.
- ;copy tempstr to edi based on _*
- push esi
- mov esi,offset tempstr
- .if (_pos) && (bptr[esi]!='-')
- mov eax,esi
- inc eax
- callp memcpy,eax,esi,sizeof tempstr - 1
- mov bptr[esi],'+'
- .endif
- callp strlen,esi
- mov ebx,eax
- .if eax < _width
- mov ecx,_width
- sub ecx,eax
- mov al,[esi]
- .if ( ( (al=='-') || (al=='+') ) && _zero )
- movsb
- dec ebx
- .endif
- .if _zero
- mov al,'0'
- .else
- mov al,32
- .endif
- rep stosb
- .endif
- mov ecx,ebx
- rep movsb
- pop esi
- jmp @@top
- addfstr: ;special for %f
- add ebp,8 ;move to next var.
- ;copy tempstr to edi based on _*
- push esi
- mov esi,offset tempstr
- .if bptr[esi+1]=='N' || bptr[esi+1]=='I' ;was it NAN or INF?
- mov edx,4
- mov _zero,0
- mov epos,0
- mov esiz,0
- jmp specialperf
- .endif
- .if (_pos) && (bptr[esi]!='-')
- mov eax,esi
- inc eax
- callp memcpy,eax,esi,sizeof tempstr - 1
- mov bptr[esi],'+'
- .endif
- call flen ;EBX= whole length ECX=pos of e EDX=size of e
- mov epos,ecx
- mov esiz,edx
- add edx,ebx
- add edx,_dec ;6+1 for dec pt
- .if _dec ;if _dec is zero then the decimal should not be printed
- inc edx ;include the dec pt
- .endif
- specialperf:
- .if edx < _width
- mov ecx,_width
- sub ecx,edx
- mov al,[esi]
- .if ( ( (al=='-') || (al=='+') ) && _zero )
- movsb
- dec edx ;just outputed 1 byte now so do not do it l8r
- .endif
- .if _zero
- mov al,'0'
- .else
- mov al,' '
- .endif
- rep stosb
- .endif
- mov ecx,edx
- sub ecx,esiz
- rep movsb ;move # first
- .if epos ;is there an exp part
- mov esi,epos ;move to exp part
- mov ecx,esiz
- rep movsb
- .endif
- pop esi
- jmp @@top
- vsprintf endp
-
- ;ret: EBX=whole len ECX=pos of e if exp # (ie: 1e3) else 0 EDX=size of exp part
- ;in : esi = string
- flen proc private uses esi
- xor ebx,ebx
- xor ecx,ecx
- xor edx,edx
- lodsb
- .while al!='.' && al!='e' && al!=0
- inc ebx
- lodsb
- .endw
- .if al==0
- ret
- .endif
- .if al=='e'
- jmp e1
- .endif
- lodsb
- .while al!='e' && al!=0
- lodsb
- .endw
- .if al==0
- ret
- .endif
- ;exp form detected
- e1:
- mov ecx,esi
- dec ecx
- inc edx ;inc for the 'e'
- lodsb
- .while al!=0
- inc edx
- lodsb
- .endw
- ret
- flen endp
-
- end
-
-